package com.alibaba.algo.domain.user;

import com.alibaba.algo.constants.Constants;
import com.alibaba.algo.cooperation.feign.vo.req.SelectRoleListByUserReqVO;
import com.alibaba.algo.cooperation.feign.vo.req.SelectRoleUserReqVO;
import com.alibaba.algo.cooperation.feign.vo.req.SelectUserListByRoleIdListReqVO;
import com.alibaba.algo.cooperation.feign.vo.res.RoleUserInfoResVO;
import com.alibaba.algo.cooperation.feign.vo.res.RpcUserInfoVO;
import com.alibaba.algo.cooperation.feign.vo.res.UserRoleInfoResVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.SelectRoleListByUserRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.SelectUserRoleRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.res.user.SelectUserRoleResponseVO;
import com.alibaba.algo.cooperation.usercomponent.vo.res.user.SysUserInfoVO;
import com.alibaba.algo.core.base.*;
import com.alibaba.algo.dao.user.SysUserRoleMapper;
import com.alibaba.algo.dtos.user.SysRoleUserDTO;
import com.alibaba.algo.entity.user.SysUser;
import com.alibaba.algo.entity.user.SysUserRole;
import com.alibaba.algo.utils.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 类SysUserRole.java的实现描述：用户角色关联Domain
 *
 * @author nieganggang 2021-03-12 16:08:17
 */
@Component
@Slf4j
public class SysUserRoleDomain extends BaseDomain<SysUserRole> {

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    /**
     * 查询当前用户所属的角色列表  有效数据
     *
     * @param userId  用户标识
     * @param sortMap 排序字段
     * @return 角色列表
     */
    public List<UserRoleInfoResVO> selectRoleListByUserId(Long userId, String appCode, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectRoleListByUserId(userId, appCode, CoreTools.getSortStr(sortMap));
    }

    /**
     * 查询当前用户所属的角色列表  全部数据
     *
     * @param userId  用户标识
     * @param sortMap 排序字段
     * @return 角色列表
     */
    public List<UserRoleInfoResVO> selectRoleListByUserIdDefaultAll(Long userId, LinkedHashMap<String, Object> sortMap, String isDeleted) {
        return sysUserRoleMapper.selectRoleListByUserIdDefaultAll(userId, CoreTools.getSortStr(sortMap), isDeleted);
    }

    /**
     * 通过多个角色ID查询用户信息列表
     *
     * @param vo
     * @param sortMap
     * @return
     */
    public List<RpcUserInfoVO> selectUserListByRoleIdListOrAppCodeList(SelectUserListByRoleIdListReqVO vo, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectUserListByRoleIdListOrAppCodeList(vo, CoreTools.getSortStr(sortMap));
    }

    public List<UserRoleInfoResVO> selectRoleListByUserIdAndApp(Long userId, String employeeCode, String userAccount, String appCode, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectRoleListByUserIdAndApp(userId, employeeCode, userAccount, appCode, CoreTools.getSortStr(sortMap));
    }

    /**
     * 角色用户分页
     *
     * @param selectUserRoleRequestVO 入参
     * @return 分页列表
     */
    public PagerEntity selectPage(SelectUserRoleRequestVO selectUserRoleRequestVO) {
        // 角色下的员工数
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setRoleId(selectUserRoleRequestVO.getRoleId());
        Integer total = sysUserRoleMapper.countByPara(sysUserRole);
        Pager pager = Pager.newInstance(total.longValue(), selectUserRoleRequestVO.getPageIndex(), selectUserRoleRequestVO.getPageSize());
        List<SelectUserRoleResponseVO> result = sysUserRoleMapper.selectPage(sysUserRole, pager.getStart(), pager.getEnd(), null);
        return new PagerEntity(total, pager.getTotalPages(), selectUserRoleRequestVO.getPageSize(), selectUserRoleRequestVO.getPageIndex(), result);
    }

    /**
     * 根据⻆⾊id获取⽤户列表
     *
     * @param roleId  角色标识
     * @param sortMap 排序
     * @return 用户列表
     */
    public List<RoleUserInfoResVO> selectUserListByRoleId(Long roleId, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectUserListByRoleId(roleId, CoreTools.getSortStr(sortMap));
    }

    /**
     * 根据⻆⾊id获取⽤户列表,支持全量查询
     *
     * @param roleId  角色标识
     * @param sortMap 排序
     * @return 用户列表
     */
    public List<RoleUserInfoResVO> selectUserListWithIsDeletedByRoleId(Long roleId, LinkedHashMap<String, Object> sortMap, String isDeleted) {
        return sysUserRoleMapper.selectUserListWithIsDeletedByRoleId(roleId, CoreTools.getSortStr(sortMap), isDeleted);
    }

    /**
     * 根据⻆⾊id获取⽤户列表附带组织信息
     *
     * @param roleId  角色标识
     * @param sortMap 排序
     * @return 用户列表
     */
    public List<RoleUserInfoResVO> selectUserListWithOrgsByRoleId(Long roleId, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectUserListWithOrgsByRoleId(roleId, CoreTools.getSortStr(sortMap));
    }

    /**
     * 根据⻆⾊id获取⽤户列表附带主组织信息
     *
     * @param roleId
     * @param orgIds
     * @param sortMap
     * @return
     */
    public List<RoleUserInfoResVO> selectUserListWithPrimaryOrgByRoleAndOrgs(Long roleId, List<Long> orgIds, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectUserListWithPrimaryOrgByRoleAndOrgs(roleId, orgIds, CoreTools.getSortStr(sortMap));
    }

    public List<RoleUserInfoResVO> selectUserListWithOrgByRoleAndOrgs(SelectRoleUserReqVO vo, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectUserListWithOrgByRoleAndOrgs(vo, CoreTools.getSortStr(sortMap));
    }

    public List<SysUserInfoVO> selectUserListByRoleId2(Long roleId, LinkedHashMap<String, Object> sortMap) {
        return sysUserRoleMapper.selectUserListByRoleId2(roleId, CoreTools.getSortStr(sortMap));
    }

    /**
     * 更新关联关系，策略是找出需要删除的关系进行删除，找出需要新增的关系进行新增
     */
    public void updateRelatedByRoleId(Long roleId, List<Long> userIdList) {
        //现有的关系
        SysUserRole param = new SysUserRole();
        param.setRoleId(roleId);
        List<SysUserRole> currentList = this.listByPara(param, null);

        if (userIdList != null) {
            out:
            for (Long userId : userIdList) {
                if (userId == null) {
                    continue;
                }
                if (currentList != null) {
                    Iterator<SysUserRole> iterator = currentList.iterator();
                    while (iterator.hasNext()) {
                        SysUserRole temp = iterator.next();
                        if (userId.equals(temp.getUserId())) {
                            iterator.remove();
                            continue out;
                        }
                    }
                }
                SysUserRole temp = new SysUserRole();
                temp.setRoleId(roleId);
                temp.setUserId(userId);
                this.insert(temp);
            }
        }
        if (currentList != null) {
            for (SysUserRole temp : currentList) {
                temp.setIsDeleted(YesOrNo.Y.name());
                this.updateById(temp);
            }
        }
    }

    /**
     * 更新关联关系，策略是不进行删除操作，按照userIdList进行更新操作
     */
    public void updateRelatedByRoleIdV2(Long roleId, List<Long> userIdList, int flag) {
        //现有的关系
        SysUserRole param = new SysUserRole();
        param.setRoleId(roleId);
        for (Long userId : userIdList) {
            param.setUserId(userId);
            List<SysUserRole> tempList = this.listByPara(param, null);
            //添加用户
            if (flag == 0) {
                if (tempList == null || tempList.size() == 0) {
                    SysUserRole temp = new SysUserRole();
                    temp.setRoleId(roleId);
                    temp.setUserId(userId);
                    this.insert(temp);
                }
            }
            //删除用户
            if (flag == 1) {
                if (tempList != null && tempList.size() >= 0) {
                    SysUserRole sysUserRole = tempList.get(0);
                    sysUserRole.setIsDeleted(YesOrNo.Y.name());
                    this.updateById(sysUserRole);
                }
            }

        }
    }


    public void mergeUserRoleRelated(Long roleId, List<SysUser> sysUserList) {
        // 检查参数合法性
        if (null == roleId || CollectionUtils.isEmpty(sysUserList)) {
            log.info("SysUserRoleDomain mergeUserRoleRelated roleId is null or sysUserList is empty");
            return;
        }
        log.info("SysUserRoleDomain mergeUserRoleRelated roleId={}", roleId);

        // 取出角色当前的人员清单
        SysUserRole param = new SysUserRole();
        param.setRoleId(roleId);
        List<SysUserRole> currentList = this.listByPara(param, null);
        if (null == currentList) {
            currentList = new ArrayList<>();
        }
        log.info("SysUserRoleDomain mergeUserRoleRelated currentList size={}", currentList.size());

        // 构建中间对象，用于提取3类数据：a比b多（新增），a和b共有(不变)，a比b少（删除）
        List<Long> sysUserIdList = new ArrayList<>(sysUserList.size());
        for (SysUser sysUser : sysUserList) {
            sysUserIdList.add(sysUser.getId());
        }
        Map<Long, SysUserRole> sysUserRoleMap = new HashMap<>();
        for (SysUserRole sysUserRole : currentList) {
            sysUserRoleMap.put(sysUserRole.getUserId(), sysUserRole);
        }

        List<SysUserRole> insertList = new ArrayList<>();
        List<Long> deleteList = new ArrayList<>();
        for (Long sysUserId : sysUserIdList) {
            if (!sysUserRoleMap.containsKey(sysUserId)) {
                //新增
                SysUserRole tmpUserRole = new SysUserRole();
                tmpUserRole.setRoleId(roleId);
                tmpUserRole.setUserId(sysUserId);
                tmpUserRole.setCreator("admin");
                tmpUserRole.setModifier(tmpUserRole.getCreator());
                tmpUserRole.setGmtCreated(LocalDateTime.now());
                tmpUserRole.setGmtModified(tmpUserRole.getGmtCreated());
                insertList.add(tmpUserRole);
            }
        }
        for (Map.Entry<Long, SysUserRole> entry : sysUserRoleMap.entrySet()) {
            if (!sysUserIdList.contains(entry.getKey())) {
                //删除
                entry.getValue().setIsDeleted(YesOrNo.Y.name());
                deleteList.add(entry.getValue().getId());
            }
        }

        // 分批次将数据更新到表
        int perCount = 200;
        if (CollectionUtils.isNotEmpty(insertList)) {
            log.info("SysUserRoleDomain mergeUserRoleRelated insertList size={}", insertList.size());
            List<List<SysUserRole>> subInsertList = CommonUtil.splitList(insertList, perCount);
            log.info("SysUserRoleDomain mergeUserRoleRelated subInsertList size={}", subInsertList.size());
            subInsertList.forEach(item -> {
                sysUserRoleMapper.batchInsert(item);
            });
        } else {
            log.info("SysUserRoleDomain mergeUserRoleRelated insertList is empty");
        }

        if (CollectionUtils.isNotEmpty(deleteList)) {
            log.info("SysUserRoleDomain mergeUserRoleRelated deleteList size={}", deleteList.size());
            List<List<Long>> subDeleteList = CommonUtil.splitList(deleteList, perCount);
            log.info("SysUserRoleDomain mergeUserRoleRelated subDeleteList size={}", subDeleteList.size());
            subDeleteList.forEach(item -> {
                sysUserRoleMapper.batchDelete(item);
            });
        } else {
            log.info("SysUserRoleDomain mergeUserRoleRelated deleteList is empty");
        }
    }

    public void batchDeleteUserRoleRelated(Long roleId) {
        // 检查参数合法性
        if (null == roleId) {
            log.info("SysUserRoleDomain batchDeleteUserRoleRelated roleId is null");
            return;
        }

        // 取出角色当前的人员清单
        SysUserRole param = new SysUserRole();
        param.setRoleId(roleId);
        List<SysUserRole> currentList = this.listByPara(param, null);
        if (CollectionUtils.isEmpty(currentList)) {
            log.info("SysUserRoleDomain batchDeleteUserRoleRelated currentList is empty");
            return;
        }
        log.info("SysUserRoleDomain batchDeleteUserRoleRelated currentList size={}", currentList.size());

        List<Long> deleteList = new ArrayList<>();
        for (SysUserRole sysUserRole : currentList) {
            deleteList.add(sysUserRole.getId());
        }
        int perCount = 200;
        if (CollectionUtils.isNotEmpty(deleteList)) {
            log.info("SysUserRoleDomain batchDeleteUserRoleRelated deleteList size={}", deleteList.size());
            List<List<Long>> subDeleteList = CommonUtil.splitList(deleteList, perCount);
            log.info("batchDeleteUserRoleRelated subDeleteList size={}", subDeleteList.size());
            subDeleteList.forEach(item -> {
                sysUserRoleMapper.batchDelete(item);
            });
        }
        log.info("SysUserRoleDomain batchDeleteUserRoleRelated deleteList is empty");
    }

    public Integer deleteByUserId(Long userId) {
        return sysUserRoleMapper.deleteByUserId(userId);
    }

    public Integer updateByUserId(SysUserRole sysUserRole) {
        return sysUserRoleMapper.updateByUserId(sysUserRole);
    }

    public Integer updateWithIsDeletedByUserIdLastModified(SysUserRole sysUserRole, LocalDateTime lastModifyTime) {
        return sysUserRoleMapper.updateWithIsDeletedByUserIdLastModified(sysUserRole, lastModifyTime);
    }

    /**
     * 查询角色用户列表
     *
     * @param vo
     * @return
     */
    public List<SysRoleUserDTO> selectRoleListByUser(SelectRoleListByUserReqVO vo) {
        return sysUserRoleMapper.selectRoleListByUser(vo);
    }

    public List<Long> selectRoleCodeByUser(SelectRoleListByUserRequestVO vo) {
        List<UserRoleInfoResVO> roleInfoList = sysUserRoleMapper.selectRoleCodeByUser(vo);
        List<Long> roleIdList = new ArrayList<>();
        if (!ObjectUtils.isEmpty(roleInfoList)) {
            roleIdList = roleInfoList.stream().map(item -> item.getRoleId()).distinct().collect(Collectors.toList());
        }
        return roleIdList;
    }

    /**
     * 将对应租户下的用户角色置为无效
     *
     * @param userId  用户id
     * @param appCode 租户信息
     * @return
     */
    public Integer invalidByUserIdAndAppCode(Long userId, String appCode) {
        return sysUserRoleMapper.invalidByUserIdAndAppCode(userId, appCode);
    }
}
